home *** CD-ROM | disk | FTP | other *** search
/ FishMarket 1.0 / FishMarket v1.0.iso / fishies / 001-025 / disk_008 / src / hack.c < prev    next >
C/C++ Source or Header  |  1992-05-06  |  20KB  |  889 lines

  1. /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
  2. /* hack.c version 1.0.1 - many small and unimportant changes */
  3. #include "hack.h"
  4. #include <stdio.h>
  5.  
  6.  
  7. extern char news0();
  8. extern char *nomovemsg;
  9. extern char *exclam();
  10. extern struct obj *addinv();
  11. extern boolean hmon();
  12.  
  13.  
  14.  
  15. /* called on movement:
  16.     1. when throwing ball+chain far away
  17.     2. when teleporting
  18.     3. when walking out of a lit room
  19.  */
  20. unsee() {
  21.     register int x,y;
  22.     register struct rm *lev;
  23.  
  24. /*
  25.     if(u.udispl){
  26.         u.udispl = 0;
  27.         newsym(u.udisx, u.udisy);
  28.     }
  29. */
  30. #ifndef QUEST
  31.     if(seehx){
  32.         seehx = 0;
  33.     } else
  34. #endif QUEST
  35.     for(x = u.ux-1; x < u.ux+2; x++)
  36.       for(y = u.uy-1; y < u.uy+2; y++) {
  37.         lev = &levl[x][y];
  38.         if(!lev->lit && lev->scrsym == '.') {
  39.             lev->scrsym =' ';
  40.             lev->new = 1;
  41.             on_scr(x,y);
  42.         }
  43.     }
  44. }
  45.  
  46. /* called:
  47.     in hack.eat.c: seeoff(0) - blind after eating rotten food
  48.     in hack.mon.c: seeoff(0) - blinded by a yellow light
  49.     in hack.mon.c: seeoff(1) - swallowed
  50.     in hack.do.c:  seeoff(0) - blind after drinking potion
  51.     in hack.do.c:  seeoff(1) - go up or down the stairs
  52.     in hack.trap.c:seeoff(1) - fall through trapdoor
  53.  */
  54. seeoff(mode)    /* 1 to redo @, 0 to leave them */
  55. {    /* 1 means misc movement, 0 means blindness */
  56.     register int x,y;
  57.     register struct rm *lev;
  58.  
  59.     if(u.udispl && mode){
  60.         u.udispl = 0;
  61.         levl[u.udisx][u.udisy].scrsym = news0(u.udisx,u.udisy);
  62.     }
  63. #ifndef QUEST
  64.     if(seehx) {
  65.         seehx = 0;
  66.     } else
  67. #endif QUEST
  68.     if(!mode) {
  69.         for(x = u.ux-1; x < u.ux+2; x++)
  70.             for(y = u.uy-1; y < u.uy+2; y++) {
  71.                 lev = &levl[x][y];
  72.                 if(!lev->lit && lev->scrsym == '.')
  73.                     lev->seen = 0;
  74.             }
  75.     }
  76. }
  77.  
  78. /* 'rogue'-like direction commands */
  79. char sdir[] = "hykulnjb";
  80. schar xdir[8] = { -1,-1,0,1,1,1,0,-1 };
  81. schar ydir[8] = { 0,-1,-1,-1,0,1,1,1 };
  82.  
  83. movecm(cmd)
  84. register char *cmd;
  85. {
  86. register char *dp;
  87.         if(!(dp = index(sdir, *cmd))) return(0);
  88.         u.dx = xdir[dp-sdir];
  89.         u.dy = ydir[dp-sdir];
  90.         return(1);
  91. }
  92. getdir()
  93. {
  94.     char buf[2];
  95.     register int x;
  96.  
  97.     pline("What direction?");
  98.     buf[0] = readchar();
  99.     buf[1] = 0;
  100.     x = movecm(buf);
  101.     if(x && Confusion) confdir();
  102.     return(x);
  103. }
  104.  
  105. confdir()
  106. {
  107.     register int x = rn2(8);
  108.     u.dx = xdir[x];
  109.     u.dy = ydir[x];
  110. }
  111.  
  112. #ifdef QUEST
  113. finddir(){
  114. register int i, ui = u.di;
  115.     for(i = 0; i <= 8; i++){
  116.         if(flags.run & 1) ui++; else ui += 7;
  117.         ui %= 8;
  118.         if(i == 8){
  119.             pline("Not near a wall.");
  120.             flags.move = multi = 0;
  121.             return(0);
  122.         }
  123.         if(!isroom(u.ux+xdir[ui], u.uy+ydir[ui]))
  124.             break;
  125.     }
  126.     for(i = 0; i <= 8; i++){
  127.         if(flags.run & 1) ui += 7; else ui++;
  128.         ui %= 8;
  129.         if(i == 8){
  130.             pline("Not near a room.");
  131.             flags.move = multi = 0;
  132.             return(0);
  133.         }
  134.         if(isroom(u.ux+xdir[ui], u.uy+ydir[ui]))
  135.             break;
  136.     }
  137.     u.di = ui;
  138.     u.dx = xdir[ui];
  139.     u.dy = ydir[ui];
  140. }
  141.  
  142. isroom(x,y)  register int x,y; {
  143.     return(isok(x,y) && (levl[x][y].typ == ROOM ||
  144.                 (levl[x][y].typ >= LDOOR && flags.run >= 6)));
  145. }
  146. #endif QUEST
  147.  
  148. isok(x,y) register int x,y; {
  149.     return(x >= 0 && x <= COLNO-1 && y >= 0 && y <= ROWNO-1);
  150. }
  151.  
  152. domove()
  153. {
  154.     xchar oldx,oldy;
  155.     register struct monst *mtmp;
  156.     register struct rm *tmpr,*ust;
  157.     struct gen *trap;
  158.     register struct obj *otmp;
  159.  
  160.     if(!u.uswallow)
  161.         wipe_engr_at(u.ux, u.uy, rnd(5));
  162.     if(inv_weight() > 0){
  163.         pline("You collapse under your load.");
  164.         nomul(0);
  165.         return;
  166.     }
  167.     if(u.uswallow) {
  168.         u.dx = u.dy = 0;
  169.         u.ux = u.ustuck->mx;
  170.         u.uy = u.ustuck->my;
  171.     } else {
  172.         if(Confusion) {
  173.             do {
  174.                 confdir();
  175.             } while(!isok(u.ux+u.dx, u.uy+u.dy) ||
  176.                 levl[u.ux+u.dx][u.uy+u.dy].typ < DOOR);
  177.         }
  178.         if(!isok(u.ux+u.dx, u.uy+u.dy)){
  179.             nomul(0);
  180.             return;
  181.         }
  182.     }
  183.  
  184.     ust = &levl[u.ux][u.uy];
  185.     oldx = u.ux;
  186.     oldy = u.uy;
  187.     if(!u.uswallow)
  188.         if(trap = g_at(u.ux+u.dx,u.uy+u.dy,ftrap)) {
  189.         if(trap->gflag & SEEN) nomul(0);
  190.     }
  191.     if(u.ustuck && !u.uswallow && (u.ux+u.dx != u.ustuck->mx ||
  192.         u.uy+u.dy != u.ustuck->my)) {
  193.         if(dist(u.ustuck->mx, u.ustuck->my) > 2){
  194.             /* perhaps it fled (or was teleported or ... ) */
  195.             u.ustuck = 0;
  196.         } else {
  197.             if(Blind) pline("You cannot escape from it!");
  198.             else pline("You cannot escape from %s!.",
  199.                 monnam(u.ustuck));
  200.             nomul(0);
  201.             return;
  202.         }
  203.     }
  204.     if(u.uswallow || (mtmp = m_at(u.ux+u.dx,u.uy+u.dy))) {
  205.     /* attack monster */
  206.         schar tmp;
  207.         boolean malive = TRUE;
  208.         register struct permonst *mdat;
  209.  
  210.         nomul(0);
  211.         gethungry();
  212.         if(multi < 0) return;    /* we just fainted */
  213.         if(u.uswallow) mtmp = u.ustuck;
  214.         mdat = mtmp->data;
  215.         if(mdat->mlet == 'L' && !mtmp->mfroz && !mtmp->msleep &&
  216.            !mtmp->mconf && mtmp->mcansee && !rn2(7) &&
  217.            (m_move(mtmp, 0) == 2 /* he died */ || /* he moved: */
  218.             mtmp->mx != u.ux+u.dx || mtmp->my != u.uy+u.dy))
  219.             goto nomon;
  220.         if(mtmp->mimic){
  221.             if(!u.ustuck && !mtmp->mflee) u.ustuck = mtmp;
  222.             switch(levl[u.ux+u.dx][u.uy+u.dy].scrsym){
  223.             case '+':
  224.                 pline("The door actually was a Mimic.");
  225.                 break;
  226.             case '$':
  227.                 pline("The chest was a Mimic!");
  228.                 break;
  229.             default:
  230.                 pline("Wait! That's a Mimic!");
  231.             }
  232.             wakeup(mtmp);    /* clears mtmp->mimic */
  233.             return;
  234.         }
  235.         wakeup(mtmp);    /* clears mtmp->mimic */
  236.         if(mtmp->mhide && mtmp->mundetected){
  237.             register struct obj *obj;
  238.             mtmp->mundetected = 0;
  239.             if((obj = o_at(mtmp->mx,mtmp->my)) && !Blind)
  240.                 pline("Wait! There's a %s hiding under %s!",
  241.                     mdat->mname, doname(obj));
  242.             return;
  243.         }
  244.         tmp = u.uluck + u.ulevel + mdat->ac + abon();
  245.         if(uwep) {
  246.             if(uwep->olet == WEAPON_SYM)
  247.                 tmp += uwep->spe;
  248.             if(uwep->otyp == TWO_HANDED_SWORD) tmp -= 1;
  249.             else if(uwep->otyp == DAGGER) tmp += 2;
  250.             else if(uwep->otyp == CRYSKNIFE) tmp += 3;
  251.             else if(uwep->otyp == SPEAR &&
  252.                 index("XDne", mdat->mlet)) tmp += 2;
  253.         }
  254.         if(mtmp->msleep) {
  255.             mtmp->msleep = 0;
  256.             tmp += 2;
  257.         }
  258.         if(mtmp->mfroz) {
  259.             tmp += 4;
  260.             if(!rn2(10)) mtmp->mfroz = 0;
  261.         }
  262.         if(mtmp->mflee) tmp += 2;
  263.         if(u.utrap) tmp -= 3;
  264.         if(tmp <= rnd(20) && !u.uswallow){
  265.             if(Blind) pline("You miss it.");
  266.             else pline("You miss %s.",monnam(mtmp));
  267.         } else {
  268.             /* we hit the monster; be careful: it might die! */
  269.  
  270.             if((malive = hmon(mtmp,uwep,0)) == TRUE) {
  271.                 /* monster still alive */
  272.                 if(!rn2(25) && mtmp->mhp < mtmp->orig_hp/2) {
  273.                     mtmp->mflee = 1;
  274.                     if(u.ustuck == mtmp && !u.uswallow)
  275.                         u.ustuck = 0;
  276.                 }
  277. #ifndef NOWORM
  278.                 if(mtmp->wormno)
  279.                     cutworm(mtmp, u.ux+u.dx, u.uy+u.dy,
  280.                         uwep ? uwep->otyp : 0);
  281. #endif NOWORM
  282.             }
  283.             if(mdat->mlet == 'a') {
  284.                 if(rn2(2)) {
  285.                 pline("You are splashed by the blob's acid!");
  286.                     losehp_m(rnd(6), mtmp);
  287.                 }
  288.                 if(!rn2(6)) corrode_weapon();
  289.                 else if(!rn2(60)) corrode_armor();
  290.             }
  291.         }
  292.         if(malive && !Blind && mdat->mlet == 'E' && rn2(3)) {
  293.             if(mtmp->mcansee) {
  294.               pline("You are frozen by the floating eye's gaze!");
  295.               nomul((u.ulevel > 6 || rn2(4)) ? rn1(20,-21) : -200);
  296.             } else {
  297.               pline("The blinded floating eye cannot defend itself.");
  298.               if(!rn2(500)) u.uluck--;
  299.             }
  300.         }
  301.         return;
  302.     }
  303. nomon:
  304.     /* not attacking an animal, so we try to move */
  305.     if(u.utrap) {
  306.         if(u.utraptype == TT_PIT) {
  307.             pline("You are still in a pit.");
  308.             u.utrap--;
  309.         } else {
  310.             pline("You are caught in a beartrap.");
  311.             if((u.dx && u.dy) || !rn2(5)) u.utrap--;
  312.         }
  313.         return;
  314.     }
  315.     tmpr = &levl[u.ux+u.dx][u.uy+u.dy];
  316.     if((tmpr->typ < DOOR) ||
  317.        (u.dx && u.dy && (tmpr->typ == DOOR || ust->typ == DOOR))){
  318.         flags.move = 0;
  319.         nomul(0);
  320.         return;
  321.     }
  322.     while(otmp = sobj_at(ENORMOUS_ROCK, u.ux+u.dx, u.uy+u.dy)) {
  323.         register xchar rx = u.ux+2*u.dx, ry = u.uy+2*u.dy;
  324.         register struct gen *gtmp;
  325.         nomul(0);
  326.         if(isok(rx,ry) && (levl[rx][ry].typ > DOOR ||
  327.             (levl[rx][ry].typ == DOOR && (!u.dx || !u.dy))) &&
  328.             !sobj_at(ENORMOUS_ROCK, rx, ry)) {
  329.             if(m_at(rx,ry)) {
  330.                 pline("You hear a monster behind the rock.");
  331.                 pline("Perhaps that's why you cannot move it.");
  332.                 return;
  333.             }
  334.             if(gtmp = g_at(rx,ry,ftrap))
  335. #include    "def.trap.h"
  336.                 switch(gtmp->gflag & TRAPTYPE) {
  337.                 case PIT:
  338.                 pline("You push the rock into a pit!");
  339.                 deltrap(gtmp);
  340.                 delobj(otmp);
  341.                 pline("It completely fills the pit!");
  342.                 continue;
  343.                 case TELEP_TRAP:
  344.                 pline("You push the rock and suddenly it disappears!");
  345.                 delobj(otmp);
  346.                 continue;
  347.                 }
  348.             otmp->ox = rx;
  349.             otmp->oy = ry;
  350.             /* pobj(otmp); */
  351.             if(cansee(rx,ry)) atl(rx,ry,otmp->olet);
  352.             if(Invis) newsym(u.ux+u.dx, u.uy+u.dy);
  353.  
  354.             { static long lastmovetime;
  355.             /* note: this var contains garbage initially and
  356.                after a restore */
  357.             if(moves > lastmovetime+2 || moves < lastmovetime)
  358.             pline("With great effort you move the enormous rock.");
  359.             lastmovetime = moves;
  360.             }
  361.         } else {
  362.             pline("You try to move the enormous rock, but in vain.");
  363.             return;
  364.         }
  365.         }
  366.     if(u.dx && u.dy && levl[u.ux][u.uy+u.dy].typ < DOOR &&
  367.         levl[u.ux+u.dx][u.uy].typ < DOOR &&
  368.         invent && inv_weight()+40 > 0) {
  369.         pline("You are carrying too much to get through.");
  370.         nomul(0);
  371.         return;
  372.     }
  373.     if(Punished &&
  374.        DIST(u.ux+u.dx, u.uy+u.dy, uchain->ox, uchain->oy) > 2){
  375.         if(carried(uball)) {
  376.             movobj(uchain, u.ux, u.uy);
  377.             goto nodrag;
  378.         }
  379.  
  380.         if(DIST(u.ux+u.dx, u.uy+u.dy, uball->ox, uball->oy) < 3){
  381.             /* leave ball, move chain under/over ball */
  382.             movobj(uchain, uball->ox, uball->oy);
  383.             goto nodrag;
  384.         }
  385.  
  386.         if(inv_weight() + (int) uball->owt/2 > 0) {
  387.             pline("You cannot %sdrag the heavy iron ball.",
  388.             invent ? "carry all that and also " : "");
  389.             nomul(0);
  390.             return;
  391.         }
  392.  
  393.         movobj(uball, uchain->ox, uchain->oy);
  394.         unpobj(uball);        /* BAH %% */
  395.         uchain->ox = u.ux;
  396.         uchain->oy = u.uy;
  397.         nomul(-2);
  398.         nomovemsg = "";
  399.     nodrag:    ;
  400.     }
  401.     u.ux += u.dx;
  402.     u.uy += u.dy;
  403.     if(flags.run) {
  404.         if(tmpr->typ == DOOR ||
  405.         (xupstair == u.ux && yupstair == u.uy) ||
  406.         (xdnstair == u.ux && ydnstair == u.uy))
  407.             nomul(0);
  408.     }
  409. /*
  410.     if(u.udispl) {
  411.         u.udispl = 0;
  412.         newsym(oldx,oldy);
  413.     }
  414. */
  415.     if(!Blind) {
  416. #ifdef QUEST
  417.         setsee();
  418. #else
  419.         if(ust->lit) {
  420.             if(tmpr->lit) {
  421.                 if(tmpr->typ == DOOR) prl1(u.ux+u.dx,u.uy+u.dy);
  422.                 else if(ust->typ == DOOR) nose1(oldx-u.dx,oldy-u.dy);
  423.             } else {
  424.                 unsee();
  425.                 prl1(u.ux+u.dx,u.uy+u.dy);
  426.             }
  427.         } else {
  428.             if(tmpr->lit) setsee();
  429.             else {
  430.                 prl1(u.ux+u.dx,u.uy+u.dy);
  431.                 if(tmpr->typ == DOOR) {
  432.                     if(u.dy) {
  433.                         prl(u.ux-1,u.uy);
  434.                         prl(u.ux+1,u.uy);
  435.                     } else {
  436.                         prl(u.ux,u.uy-1);
  437.                         prl(u.ux,u.uy+1);
  438.                     }
  439.                 }
  440.             }
  441.             nose1(oldx-u.dx,oldy-u.dy);
  442.         }
  443. #endif QUEST
  444.     } else {
  445.         pru();
  446.     }
  447.     if(!flags.nopick) pickup();
  448.     if(trap) dotrap(trap);        /* fall into pit, arrow trap, etc. */
  449.     (void) inshop();
  450.     if(!Blind) read_engr_at(u.ux,u.uy);
  451. }
  452.  
  453. movobj(obj, ox, oy)
  454. register struct obj *obj;
  455. register int ox, oy;
  456. {
  457.     /* Some dirty programming to get display right */
  458.     freeobj(obj);
  459.     unpobj(obj);
  460.     obj->nobj = fobj;
  461.     fobj = obj;
  462.     obj->ox = ox;
  463.     obj->oy = oy;
  464. }
  465.  
  466. dopickup(){
  467.     if(!g_at(u.ux,u.uy,fgold) && !o_at(u.ux,u.uy)) {
  468.         pline("There is nothing here to pick up.");
  469.         return(0);
  470.     }
  471.     if(Levitation) {
  472.         pline("You cannot reach the floor.");
  473.         return(1);
  474.     }
  475.     pickup();
  476.     return(1);
  477. }
  478.  
  479. pickup(){
  480. register struct gen *gold;
  481. register struct obj *obj, *obj2;
  482. register int wt;
  483.     if(Levitation) return;
  484.     while(gold = g_at(u.ux,u.uy,fgold)) {
  485.         pline("%u gold piece%s.", gold->gflag, plur(gold->gflag));
  486.         u.ugold += gold->gflag;
  487.         flags.botl = 1;
  488.         freegold(gold);
  489.         if(flags.run) nomul(0);
  490.         if(Invis) newsym(u.ux,u.uy);
  491.     }
  492.     for(obj = fobj; obj; obj = obj2) {
  493.         obj2 = obj->nobj;    /* perhaps obj will be picked up */
  494.         if(obj->ox == u.ux && obj->oy == u.uy) {
  495.         if(flags.run) nomul(0);
  496.  
  497. #define    DEAD_c    CORPSE+('c'-'a'+'Z'-'@'+1)
  498.         if(obj->otyp == DEAD_COCKATRICE && !uarmg){
  499.             pline("Touching the dead cockatrice is a fatal mistake.");
  500.             pline("You turn to stone.");
  501.             killer = "cockatrice cadaver";
  502.             done("died");
  503.         }
  504.  
  505.         if(obj->otyp == SCR_SCARE_MONSTER){
  506.           if(!obj->spe) obj->spe = 1;
  507.           else {
  508.             /* Note: perhaps the 1st pickup failed: you cannot
  509.             carry anymore, and so we never dropped it -
  510.             let's assume that treading on it twice also
  511.             destroys the scroll */
  512.             pline("The scroll turns to dust as you pick it up.");
  513.             delobj(obj);
  514.             continue;
  515.           }
  516.         }
  517.  
  518.         /* do not pick up uchain */
  519.         if(Punished && obj == uchain)
  520.             continue;
  521.  
  522.         wt = inv_weight() + obj->owt;
  523.         if(wt > 0) {
  524.             if(obj->quan > 1) {
  525.                 /* see how many we can lift */
  526.                 extern struct obj *splitobj();
  527.                 int savequan = obj->quan;
  528.                 int iw = inv_weight();
  529.                 int qq;
  530.                 for(qq = 1; qq < savequan; qq++){
  531.                     obj->quan = qq;
  532.                     if(iw + weight(obj) > 0)
  533.                         break;
  534.                 }
  535.                 obj->quan = savequan;
  536.                 qq--;
  537.                 /* we can carry qq of them */
  538.                 if(!qq) goto too_heavy;
  539.             pline("You can only carry %s of the %s lying here.",
  540.                     (qq == 1) ? "one" : "some",
  541.                     doname(obj));
  542.                 (void) splitobj(obj, qq);
  543.                 /* note: obj2 is set already, so we'll never
  544.                  * encounter the other half; if it should be
  545.                  * otherwise then write
  546.                  *    obj2 = splitobj(obj,qq);
  547.                  */
  548.                 goto lift_some;
  549.             }
  550.         too_heavy:
  551.             pline("There %s %s here, but %s.",
  552.                 (obj->quan == 1) ? "is" : "are",
  553.                 doname(obj),
  554.                 !invent ? "it is too heavy for you to lift"
  555.                     : "you cannot carry anymore");
  556.             break;
  557.         }
  558.     lift_some:
  559.         if(inv_cnt() >= 52) {
  560.             pline("Your knapsack cannot accomodate anymore items.");
  561.             break;
  562.         }
  563.         if(wt > -5) pline("You have a little trouble lifting");
  564.         freeobj(obj);
  565.         if(Invis) newsym(u.ux,u.uy);
  566.         addtobill(obj);       /* sets obj->unpaid if necessary */
  567.         { int pickquan = obj->quan;
  568.           int mergquan;
  569.         if(!Blind) obj->dknown = 1;    /* this is done by prinv(),
  570.                  but addinv() needs it already for merging */
  571.         obj = addinv(obj);    /* might merge it with other objects */
  572.           mergquan = obj->quan;
  573.           obj->quan = pickquan;    /* to fool prinv() */
  574.         prinv(obj);
  575.           obj->quan = mergquan;
  576.         }
  577.         }
  578.     }
  579. }
  580.  
  581. /* stop running if we see something interesting */
  582. /* turn around a corner if that is the only way we can proceed */
  583. /* do not turn left or right twice */
  584. lookaround(){
  585. register int x,y,i,x0,y0,m0,i0 = 9;
  586. register int corrct = 0, noturn = 0;
  587. register struct monst *mtmp;
  588. #ifdef lint
  589.     /* suppress "used before set" message */
  590.     x0 = y0 = 0;
  591. #endif lint
  592.     if(Blind || flags.run == 0) return;
  593.     if(flags.run == 1 && levl[u.ux][u.uy].typ >= ROOM) return;
  594. #ifdef QUEST
  595.     if(u.ux0 == u.ux+u.dx && u.uy0 == u.uy+u.dy) goto stop;
  596. #endif QUEST
  597.     for(x = u.ux-1; x <= u.ux+1; x++) for(y = u.uy-1; y <= u.uy+1; y++){
  598.         if(x == u.ux && y == u.uy) continue;
  599.         if(!levl[x][y].typ) continue;
  600.         if((mtmp = m_at(x,y)) && !mtmp->mimic &&
  601.             (!mtmp->minvis || See_invisible)){
  602.             if(!mtmp->mtame || (x == u.ux+u.dx && y == u.uy+u.dy))
  603.                 goto stop;
  604.         } else mtmp = 0; /* invisible M cannot influence us */
  605.         if(x == u.ux-u.dx && y == u.uy-u.dy) continue;
  606.         switch(levl[x][y].scrsym){
  607.         case '|':
  608.         case '-':
  609.         case '.':
  610.         case ' ':
  611.             break;
  612.         case '+':
  613.             if(x != u.ux && y != u.uy) break;
  614.             if(flags.run != 1) goto stop;
  615.             /* fall into next case */
  616.         case CORR_SYM:
  617.         corr:
  618.             if(flags.run == 1 || flags.run == 3) {
  619.                 i = DIST(x,y,u.ux+u.dx,u.uy+u.dy);
  620.                 if(i > 2) break;
  621.                 if(corrct == 1 && DIST(x,y,x0,y0) != 1)
  622.                     noturn = 1;
  623.                 if(i < i0) {
  624.                     i0 = i;
  625.                     x0 = x;
  626.                     y0 = y;
  627.                     m0 = mtmp ? 1 : 0;
  628.                 }
  629.             }
  630.             corrct++;
  631.             break;
  632.         case '^':
  633.             if(flags.run == 1) goto corr;    /* if you must */
  634.             if(x == u.ux+u.dx && y == u.uy+u.dx) goto stop;
  635.             break;
  636.         default:    /* e.g. objects or trap or stairs */
  637.             if(flags.run == 1) goto corr;
  638.             if(mtmp) break;        /* d */
  639.         stop:
  640.             nomul(0);
  641.             return;
  642.         }
  643.     }
  644. #ifdef QUEST
  645.     if(corrct > 0 && (flags.run == 4 || flags.run == 5)) goto stop;
  646. #endif QUEST
  647.     if(corrct > 1 && flags.run == 2) goto stop;
  648.     if((flags.run == 1 || flags.run == 3) && !noturn && !m0 && i0 &&
  649.         (corrct == 1 || (corrct == 2 && i0 == 1))) {
  650.         /* make sure that we do not turn too far */
  651.         if(i0 == 2) {
  652.             if(u.dx == y0-u.uy && u.dy == u.ux-x0)
  653.             i = 2;        /* straight turn right */
  654.             else
  655.             i = -2;        /* straight turn left */
  656.         } else if(u.dx && u.dy) {
  657.             if((u.dx == u.dy && y0 == u.uy) ||
  658.             (u.dx != u.dy && y0 != u.uy))
  659.             i = -1;        /* half turn left */
  660.             else
  661.             i = 1;        /* half turn right */
  662.         } else {
  663.             if((x0-u.ux == y0-u.uy && !u.dy) ||
  664.             (x0-u.ux != y0-u.uy && u.dy))
  665.             i = 1;        /* half turn right */
  666.             else
  667.             i = -1;        /* half turn left */
  668.         }
  669.         i += u.last_str_turn;
  670.         if(i <= 2 && i >= -2) {
  671.             u.last_str_turn = i;
  672.             u.dx = x0-u.ux, u.dy = y0-u.uy;
  673.         }
  674.     }
  675. }
  676.  
  677. #ifdef QUEST
  678. cansee(x,y) xchar x,y; {
  679. register int dx,dy,adx,ady,sdx,sdy,dmax,d;
  680.     if(Blind) return(0);
  681.     if(!isok(x,y)) return(0);
  682.     d = dist(x,y);
  683.     if(d < 3) return(1);
  684.     if(d > u.uhorizon*u.uhorizon) return(0);
  685.     if(!levl[x][y].lit)
  686.         return(0);
  687.     dx = x - u.ux;    adx = abs(dx);    sdx = sgn(dx);
  688.     dy = y - u.uy;  ady = abs(dy);    sdy = sgn(dy);
  689.     if(dx == 0 || dy == 0 || adx == ady){
  690.         dmax = (dx == 0) ? ady : adx;
  691.         for(d = 1; d <= dmax; d++)
  692.             if(!rroom(sdx*d,sdy*d))
  693.                 return(0);
  694.         return(1);
  695.     } else if(ady > adx){
  696.         for(d = 1; d <= ady; d++){
  697.             if(!rroom(sdx*( (d*adx)/ady ), sdy*d) ||
  698.                !rroom(sdx*( (d*adx-1)/ady+1 ), sdy*d))
  699.                 return(0);
  700.         }
  701.         return(1);
  702.     } else {
  703.         for(d = 1; d <= adx; d++){
  704.             if(!rroom(sdx*d, sdy*( (d*ady)/adx )) ||
  705.                !rroom(sdx*d, sdy*( (d*ady-1)/adx+1 )))
  706.                 return(0);
  707.         }
  708.         return(1);
  709.     }
  710. }
  711.  
  712. rroom(x,y) register int x,y; {
  713.     return(levl[u.ux+x][u.uy+y].typ >= ROOM);
  714. }
  715.  
  716. #else
  717.  
  718. cansee(x,y) xchar x,y; {
  719.     if(Blind || u.uswallow) return(0);
  720.     if(dist(x,y) < 3) return(1);
  721.     if(levl[x][y].lit && seelx <= x && x <= seehx && seely <= y &&
  722.         y <= seehy) return(1);
  723.     return(0);
  724. }
  725. #endif QUEST
  726.  
  727. sgn(a) register int a; {
  728.     return((a> 0) ? 1 : (a == 0) ? 0 : -1);
  729. }
  730.  
  731. pow(num) /* returns 2 to the num */
  732. register unsigned num;
  733. {
  734.     return(1 << num);
  735. }
  736.  
  737. #ifdef QUEST
  738. setsee()
  739. {
  740.     register int x,y;
  741.  
  742.     if(Blind) {
  743.         pru();
  744.         return;
  745.     }
  746.     for(y = u.uy-u.uhorizon; y <= u.uy+u.uhorizon; y++)
  747.         for(x = u.ux-u.uhorizon; x <= u.ux+u.uhorizon; x++) {
  748.             if(cansee(x,y))
  749.                 prl(x,y);
  750.     }
  751. }
  752.  
  753. #else
  754.  
  755. setsee()
  756. {
  757.     register int x,y;
  758.  
  759.     if(Blind) {
  760.         pru();
  761.         return;
  762.     }
  763.     if(!levl[u.ux][u.uy].lit) {
  764.         seelx = u.ux-1;
  765.         seehx = u.ux+1;
  766.         seely = u.uy-1;
  767.         seehy = u.uy+1;
  768.     } else {
  769.         for(seelx = u.ux; levl[seelx-1][u.uy].lit; seelx--);
  770.         for(seehx = u.ux; levl[seehx+1][u.uy].lit; seehx++);
  771.         for(seely = u.uy; levl[u.ux][seely-1].lit; seely--);
  772.         for(seehy = u.uy; levl[u.ux][seehy+1].lit; seehy++);
  773.     }
  774.     for(y = seely; y <= seehy; y++)
  775.         for(x = seelx; x <= seehx; x++) {
  776.             prl(x,y);
  777.     }
  778.     if(!levl[u.ux][u.uy].lit) seehx = 0; /* seems necessary elsewhere */
  779.     else {
  780.         if(seely == u.uy) for(x = u.ux-1; x <= u.ux+1; x++) prl(x,seely-1);
  781.         if(seehy == u.uy) for(x = u.ux-1; x <= u.ux+1; x++) prl(x,seehy+1);
  782.         if(seelx == u.ux) for(y = u.uy-1; y <= u.uy+1; y++) prl(seelx-1,y);
  783.         if(seehx == u.ux) for(y = u.uy-1; y <= u.uy+1; y++) prl(seehx+1,y);
  784.     }
  785. }
  786. #endif QUEST
  787.  
  788. nomul(nval)
  789. register int nval;
  790. {
  791.     if(multi < 0) return;
  792.     multi = nval;
  793.     flags.mv = flags.run = 0;
  794. }
  795.  
  796. abon()
  797. {
  798.     if(u.ustr == 3) return(-3);
  799.     else if(u.ustr < 6) return(-2);
  800.     else if(u.ustr < 8) return(-1);
  801.     else if(u.ustr < 17) return(0);
  802.     else if(u.ustr < 69) return(1);    /* up to 18/50 */
  803.     else if(u.ustr < 118) return(2);
  804.     else return(3);
  805. }
  806.  
  807. dbon()
  808. {
  809.     if(u.ustr < 6) return(-1);
  810.     else if(u.ustr < 16) return(0);
  811.     else if(u.ustr < 18) return(1);
  812.     else if(u.ustr == 18) return(2);    /* up to 18 */
  813.     else if(u.ustr < 94) return(3);    /* up to 18/75 */
  814.     else if(u.ustr < 109) return(4);    /* up to 18/90 */
  815.     else if(u.ustr < 118) return(5);    /* up to 18/99 */
  816.     else return(6);
  817. }
  818.  
  819. losestr(num)
  820. register int num;
  821. {
  822.     u.ustr -= num;
  823.     while(u.ustr < 3) {
  824.         u.ustr++;
  825.         u.uhp -= 6;
  826.         u.uhpmax -= 6;
  827.     }
  828.     flags.botl = 1;
  829. }
  830.  
  831. losehp(n,knam)
  832. register int n;
  833. register char *knam;
  834. {
  835.     u.uhp -= n;
  836.     if(u.uhp > u.uhpmax)
  837.         u.uhpmax = u.uhp;    /* perhaps n was negative */
  838.     flags.botl = 1;
  839.     if(u.uhp < 1)
  840.         killer = knam;    /* the thing that killed you */
  841. }
  842.  
  843. losehp_m(n,mtmp)
  844. register int n;
  845. register struct monst *mtmp;
  846. {
  847.     u.uhp -= n;
  848.     flags.botl = 1;
  849.     if(u.uhp < 1) done_in_by(mtmp);
  850. }
  851.  
  852. losexp()    /* hit by V or W */
  853. {
  854.     register int num;
  855.  
  856.     if(u.ulevel > 1) pline("Goodbye level %d.",u.ulevel--);
  857.     else u.uhp = -1;
  858.     num = rnd(10);
  859.     u.uhp -= num;
  860.     u.uhpmax -= num;
  861.     u.uexp = 10*pow(u.ulevel-1);
  862.     flags.botl = 1;
  863. }
  864.  
  865. inv_weight(){
  866. register struct obj *otmp = invent;
  867. register int wt = 0;
  868. register int carrcap = 5*(((u.ustr > 18) ? 20 : u.ustr) + u.ulevel);
  869.     if(carrcap > MAX_CARR_CAP) carrcap = MAX_CARR_CAP;
  870.     if(Wounded_legs & LEFT_SIDE) carrcap -= 10;
  871.     if(Wounded_legs & RIGHT_SIDE) carrcap -= 10;
  872.     while(otmp){
  873.         wt += otmp->owt;
  874.         otmp = otmp->nobj;
  875.     }
  876.     return(wt - carrcap);
  877. }
  878.  
  879. inv_cnt(){
  880. register struct obj *otmp = invent;
  881. register int ct = 0;
  882.     while(otmp){
  883.         ct++;
  884.         otmp = otmp->nobj;
  885.     }
  886.     return(ct);
  887. }
  888.  
  889.